#include <iostream>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "bglProgram.h"
#include "bglTexture2D.h"
#include "bglWidget.h"

class BaseWidget : public BGLWidget
{
private:
	unsigned int m_VBO; //顶点缓冲区对象
	unsigned int m_VAO; //顶点数组对象
	unsigned int m_EBO;

	unsigned int m_textureId0;  //纹理
	unsigned int m_textureId1;

	BGLProgram m_program;

public:
	BaseWidget() : BGLWidget()
	{
		
	}

	~BaseWidget()
	{

	}

	virtual void Init() 
	{
		float vertices[] = {
		//     ---- 位置 ----       ---- 颜色 ----     - 纹理坐标 -
			0.5f,   0.5f, 0.0f,    1.0f, 0.0f, 0.0f,   1.0f, 1.0f,   // 右上
			0.5f,  -0.5f, 0.0f,    0.0f, 1.0f, 0.0f,   1.0f, 0.0f,   // 右下
			-0.5f, -0.5f, 0.0f,    0.0f, 0.0f, 1.0f,   0.0f, 0.0f,   // 左下
			-0.5f,  0.5f, 0.0f,    1.0f, 1.0f, 0.0f,   0.0f, 1.0f    // 左上
		};

		unsigned int indices[] = {  
			0, 1, 3, // first triangle
			1, 2, 3  // second triangle
		};

		glGenVertexArrays(1, &m_VAO); //创建顶点数组对象
		glBindVertexArray(m_VAO); //绑定顶点数组

		glGenBuffers(1, &m_VBO);  //创建顶点缓冲区
		glBindBuffer(GL_ARRAY_BUFFER, m_VBO); //绑定顶点缓冲区
		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //GL_STATIC_DRAW:数据不会或几乎不会改变。

		glGenBuffers(1, &m_EBO);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
    	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
		
		//设置顶点属性的属性
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
		glEnableVertexAttribArray(0); //启用0号顶点属性

		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
		glEnableVertexAttribArray(1); //启用1号顶点属性

		glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
		glEnableVertexAttribArray(2); //启用2号顶点属性


		m_textureId0 = BGLTexture2D().createTextureFromImage("./data/images/girl0.jpg");
		m_textureId1 = BGLTexture2D().createTextureFromImage("./data/images/face.png");

		m_program.createProgramFromFile("./data/shaders/08_3d0/vert.glsl", "./data/shaders/08_3d0/frag.glsl"); //创建shader program
	
		//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //绘制模式
		//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);//
	}

	virtual void Render()
	{
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

		int screenWidth, screenHeight;
		GetWindowSize(&screenWidth, &screenHeight);

		m_program.begin();

		glm::mat4 model = glm::mat4(1.0f);
		//model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0f, 0.0f, 0.0f));
		model = glm::rotate(model, (float)glfwGetTime() * glm::radians(50.0f), glm::vec3(0.5f, 1.0f, 0.0f));
		m_program.setMat4("model", model);

		glm::mat4 view = glm::mat4(1.0f);
		view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
		m_program.setMat4("view", view);

		glm::mat4 projection = glm::mat4(1.0f);
		projection = glm::perspective(glm::radians(45.0f), (float)screenWidth / screenHeight, 0.1f, 100.0f);
		m_program.setMat4("projection", projection);

		glUniform1i(glGetUniformLocation(m_program.getId(), "ourTexture0"), 0);
		glUniform1i(glGetUniformLocation(m_program.getId(), "ourTexture1"), 1);

		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, m_textureId0);

		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D, m_textureId1);

		glBindVertexArray(m_VAO);
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

		m_program.end();
	}

	virtual void FramebufferSizeCallback(GLFWwindow* window, int width, int height)
	{
		if(width != 0 && height != 0)
		{
			glViewport(0, 0, width, height);
		}
	}
}; 

int main() {
	
	BaseWidget widget;
	widget.Run();

	return 0;
}